﻿using BLL;
using System.Net;

namespace JLMiddlewares
{
    /// <summary>
    /// 替换真实IP为代理后的IP
    /// </summary>
    public class RealIpMiddleware
    {
        private readonly RequestDelegate _next;

        public RealIpMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public Task Invoke(HttpContext context)
        {
            var headers = context.Request.Headers;
            if (headers.ContainsKey("X-Forwarded-For"))
            {
                try
                {
                    if (ConfigBLL.Config.IsProxyReplaceIP)
                    {
                        string _headerStr = string.Empty;
                        if (!string.IsNullOrEmpty(headers["X-Real-IP"].ToString()))
                        {
                            _headerStr = headers["X-Real-IP"].ToString();
                        }
                        else if (!string.IsNullOrEmpty(headers["X-Forwarded-For"].ToString()))
                        {
                            _headerStr = headers["X-Forwarded-For"].ToString();
                        }
                        string _ip = GetIP(_headerStr);
                        if (!string.IsNullOrEmpty(_ip))
                        {
                            context.Connection.RemoteIpAddress = System.Net.IPAddress.Parse(_ip);
                        }

                    }
                    else
                    {
                        if (headers["X-Forwarded-For"].ToString().IndexOf(",") > -1)
                        {
                            context.Connection.RemoteIpAddress = System.Net.IPAddress.Parse(headers["X-Forwarded-For"].ToString().Split(',', StringSplitOptions.RemoveEmptyEntries)[0]);
                        }
                        else if (headers["X-Forwarded-For"].ToString().IndexOf(":") > -1)
                        {
                            context.Connection.RemoteIpAddress = System.Net.IPAddress.Parse(headers["X-Forwarded-For"].ToString().Split(':', StringSplitOptions.RemoveEmptyEntries)[0]);
                        }
                    }
                }
                catch
                {

                }
            }
            return _next(context);
        }

        /// <summary>
        /// 获取最后一个非内网IP
        /// </summary>
        /// <returns></returns>
        private string GetIP(string headerStr)
        {
            string[] _ipList = headerStr.Split(',', StringSplitOptions.RemoveEmptyEntries);
            if (_ipList.Length == 0)
            {
                return string.Empty;
            }
            for (int i = _ipList.Length - 1; i >= 0; i--)
            {
                string _ip = _ipList[i];
                if (_ip.IndexOf(":") > -1)
                {
                    _ip = _ip.Split(':', StringSplitOptions.RemoveEmptyEntries)[0];
                }
                if (!IsPrivateNetwork(_ip))
                {
                    return _ip;
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// 判断是否为内网代理服务器IP
        /// </summary>
        /// <param name="ipv4Address">IP地址</param>
        /// <returns></returns>
        private bool IsPrivateNetwork(string ipv4Address)
        {
            if (IPAddress.TryParse(ipv4Address, out var ip))
            {
                byte[] ipBytes = ip.GetAddressBytes();
                if (ipBytes[0] == 10) return true;
                if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
                if (ipBytes[0] == 192 && ipBytes[1] == 168) return true;
            }
            return false;
        }

    }
}
